//============================================================================
// Copyright (C) 2010 Brett R. Jones
// All Rights Reserved
//
// You may redistribute and/or modify for non commercial and commercial uses
// provided this copyright notice remains in place and is not modified
//
// This code is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================
#include "DtwGame.h"
#include "irrlicht/CBillboardSceneNode.h"
//------------------------------------------------------------------------------
//! determine dimensions of game world etc
void DtwStatePlay::CalculateWorldLimits( void )
{
	log_msg( 0, "Calculating World Limits\n" );
	irr::core::vector3df v3fObjPos;
	irr::core::position2d<irr::s32> v2dRetPos;
	v3fObjPos.set(0.0f, 0.0f, 0.0f);
	m_poIrrBase->WorldToScreen( v3fObjPos, v2dRetPos );
	log_msg( 0, "Screen position of origin %d, %d\n", v2dRetPos.X, v2dRetPos.Y);

	v3fObjPos.set(100.0f, 0.0f, 0.0f);
	m_poIrrBase->WorldToScreen( v3fObjPos, v2dRetPos );
	log_msg( 0, "Screen position of +100 X %d, %d\n", v2dRetPos.X, v2dRetPos.Y);

	v3fObjPos.set(0.0f, 0.0f, 100.0f);
	m_poIrrBase->WorldToScreen( v3fObjPos, v2dRetPos );
	log_msg( 0, "Screen position of +100 Z %d, %d\n", v2dRetPos.X, v2dRetPos.Y);


	// get where upper center pixel of screen intersects world x-z plane
	if( false == m_poIrrBase->GetXZPlaneIntersect( m_poIrrBase->m_iScnSizeX >> 1, 1, m_v3fPlusXExtreme ) )
	{
		log_msg( 0, "Failed Plus X extreme");
	}
	else
	{
		log_msg( 0, "Plus X Extreme  %3.2f, %3.2f, %3.2f\n", m_v3fPlusXExtreme.X, m_v3fPlusXExtreme.Y, m_v3fPlusXExtreme.Z);
	}
	// get where lower center pixel of screen intersects world x-y plane
	if( false == m_poIrrBase->GetXZPlaneIntersect( m_poIrrBase->m_iScnSizeX >> 1, m_poIrrBase->m_iScnSizeY -1, m_v3fMinusXExtreme ) )
	{
		log_msg( 0, "Failed Minus X extreme");
	}
	else
	{
		log_msg( 0, "Minus X Extreme  %3.2f, %3.2f, %3.2f\n", m_v3fMinusXExtreme.X, m_v3fMinusXExtreme.Y, m_v3fMinusXExtreme.Z);
	}
	// get where upper left pixel of screen intersects world x-y plane
	if( false == m_poIrrBase->GetXZPlaneIntersect( 1, 1, m_v3fPlusZExtreme ) )
	{
		log_msg( 0, "Failed Plus Z extreme");
	}
	else
	{
		log_msg( 0, "Plus Z Extreme  %3.2f, %3.2f, %3.2f\n", m_v3fPlusZExtreme.X, m_v3fPlusZExtreme.Y, m_v3fPlusZExtreme.Z);
	}
	// get where upper right pixel of screen intersects world x-y plane
	if( false == m_poIrrBase->GetXZPlaneIntersect( m_poIrrBase->m_iScnSizeX-1, 1, m_v3fMinusZExtreme ) )
	{
		log_msg( 0, "Failed Minus Z extreme");
	}
	else
	{
		log_msg( 0, "Minus Z Extreme  %3.2f, %3.2f, %3.2f\n", m_v3fMinusZExtreme.X, m_v3fMinusZExtreme.Y, m_v3fMinusZExtreme.Z);
	}
	m_oWorldBBox.addInternalPoint(m_v3fMinusZExtreme);
	m_oWorldBBox.addInternalPoint(m_v3fMinusXExtreme);
	m_oWorldBBox.addInternalPoint(m_v3fPlusXExtreme);
	m_oWorldBBox.addInternalPoint(m_v3fPlusZExtreme);

	irr::core::vector3df v3fMinEdge;
	irr::core::vector3df v3fMaxEdge;

	m_oWorldBBox.getMinEdge(v3fMinEdge);
	m_oWorldBBox.getMaxEdge(v3fMaxEdge);

	log_msg( 0, "WorldBBox (%3.0f, %3.0f, %3.0f) to(%3.0f, %3.0f, %3.0f)\n",
			v3fMinEdge.X, v3fMinEdge.Y, v3fMinEdge.Z,
			v3fMaxEdge.X, v3fMaxEdge.Y, v3fMaxEdge.Z );
	// get where lower left pixel of screen intersects world x-y plane
	if( false == m_poIrrBase->GetXZPlaneIntersect( 1, m_poIrrBase->m_iScnSizeY -1, m_v3fPlusZMin ) )
	{
		log_msg( 0, "Failed Plus Z Minumum");
	}
	else
	{
		log_msg( 0, "Plus Z Minumum  %3.2f, %3.2f, %3.2f\n", m_v3fPlusZMin.X, m_v3fPlusZMin.Y, m_v3fPlusZMin.Z);
	}
	// get where upper right pixel of screen intersects world x-y plane
	if( false == m_poIrrBase->GetXZPlaneIntersect( m_poIrrBase->m_iScnSizeX-1, m_poIrrBase->m_iScnSizeY -1, m_v3fMinusZMin ) )
	{
		log_msg( 0, "Failed Minus Z Minumum");
	}
	else
	{
		log_msg( 0, "Minus Z Minumum  %3.2f, %3.2f, %3.2f\n", m_v3fMinusZMin.X, m_v3fMinusZMin.Y, m_v3fMinusZMin.Z);
	}

}

//------------------------------------------------------------------------------
//! place object positions etc
void DtwStatePlay::DetermineGeometry( void )
{
	// screen layout in irrlicht coords
	//					+X Extream
	//					     | +Y
	//                       |/	
	//     -Z Extream --------------- +Z Extream
	//					     |
	//                       |	
	//					-X Extream
	// because there is such a wide variance in screen sizes we need to add some kind of scaling so the size of earth etc is somewhat the
	// same on all phones
	// assume our basic low end phone is 320x480 and its scaling is 1.0
	// scaling for 480x854 phone would be 854/480 = 1.78
	//m_f32WorldScale = ((float)m_iScnSizeY)/480.0f;
	m_f32WorldScale = 1.0f;

//	log_msg( 0, "earth %d comet 1 %d comet 2 %d \n", 
//					m_poEntEarth->m_poSceneNode, 
//					m_poEntCometRed->m_poSceneNode, 
//					m_poEntCometBlue->m_poSceneNode );

	//m_poEntEarth->m_poSceneNode->setScale( irr::core::vector3df(60.0f * m_f32WorldScale, 60.0f * m_f32WorldScale, 60.0f * m_f32WorldScale) );
	// irrlicht doesnt scale the bounding box so doit
	//irr::scene::CBillboardSceneNode * poTmpNode = (irr::scene::CBillboardSceneNode *)((irr::scene::IBillboardSceneNode*)m_poEntCometRed->m_poSceneNode);

	log_msg( 0, "Calculating Geometry: getting earth %d size\n", m_poEntEarth );
	vx_assert( m_poEntEarth );
	vx_assert( m_poEntEarth->m_poSceneNode );

	irr::core::aabbox3d<irr::f32> oBBox = m_poEntEarth->m_poSceneNode->getBoundingBox();
	oBBox.setScale( m_poEntEarth->m_poSceneNode->getScale() );
	m_f32EarthSize = oBBox.getWidth();

	log_msg( 0, "Calculating Geometry: getting red comet size\n" );
	//m_poComet1Node->setScale( irr::core::vector3df(5.0f * m_f32WorldScale, 5.0f * m_f32WorldScale, 5.0f * m_f32WorldScale) );
	oBBox = m_poEntCometRed->m_poSceneNode->getBoundingBox();
	// irrlicht doesn't scale the bounding box so doit
	m_poEntCometRed->m_poSceneNode->setBBoxScale( m_poEntCometRed->m_poSceneNode->getScale() );
	//log_msg( 0, "comet 1 size after scale %3.2f\n", oBBox.getWidth());
	m_f32CometRedSize = oBBox.getWidth();

	log_msg( 0, "Calculating Geometry: getting blue comet size\n" );
	oBBox = m_poEntCometBlue->m_poSceneNode->getBoundingBox();
	// irrlicht doesn't scale the bounding box so doit
	m_poEntCometBlue->m_poSceneNode->setBBoxScale( m_poEntCometBlue->m_poSceneNode->getScale() );
	m_f32CometBlueSize = oBBox.getWidth();


	log_msg( 0, "Calculating Geometry earth size %3.1f comet 1 size %3.1f comet 2 size %3.1f\n", m_f32EarthSize, m_f32CometRedSize, m_f32CometBlueSize );

	// calculate where to place earth
	// place at y axis just inside world x limit
	m_v3fEarthPos.set( m_v3fPlusXExtreme.X - (m_f32EarthSize * 2.5f), 0.0f,  0.0f);
	log_msg( 0, "earth pos (%3.1f, %3.1f, %3.1f)\n", m_v3fEarthPos.X, m_v3fEarthPos.Y, m_v3fEarthPos.Z);
	m_poEntEarth->SetIrrPlusPhysicsPosition( m_v3fEarthPos );
	m_poEntEarth->SetStartPosition( m_v3fEarthPos );

	// calculate starting position of comet Red
	// place inside world -y limit at 1/3 width of screen
	F32 f32OneThirdZ = (VxAbs(m_v3fPlusZMin.Z) + VxAbs( m_v3fMinusZMin.Z)) * 0.333333333333f;
	log_msg( 0, "1 third distance across world %3.1f\n", f32OneThirdZ );

	// set comet start positions
	m_v3fCometRedStartPos.set(	m_v3fMinusXExtreme.X + m_f32CometRedSize,
								0.0f,
								m_v3fPlusZMin.Z - f32OneThirdZ );
	log_msg( 0, "comet red pos (%3.1f, %3.1f, %3.1f)\n", m_v3fCometRedStartPos.X, m_v3fCometRedStartPos.Y, m_v3fCometRedStartPos.Z);
	m_poEntCometRed->SetIrrPlusPhysicsPosition( m_v3fCometRedStartPos );
	m_poEntCometRed->SetStartPosition( m_v3fCometRedStartPos );

	// calculate starting position of comet Blue
	// place inside world -y limit at 2/3 width of screen
	m_v3fCometBlueStartPos.set(	m_v3fMinusXExtreme.X + m_f32CometBlueSize,
								0.0f,
								m_v3fPlusZMin.Z - (f32OneThirdZ  * 2) );
	log_msg( 0, "comet blue pos (%3.1f, %3.1f, %3.1f)\n", m_v3fCometBlueStartPos.X, m_v3fCometBlueStartPos.Y, m_v3fCometBlueStartPos.Z);
	m_poEntCometBlue->SetIrrPlusPhysicsPosition( m_v3fCometBlueStartPos );
	m_poEntCometBlue->SetStartPosition( m_v3fCometBlueStartPos );

	// calculate red asteroid starting position
	m_v3fAsteroidRedStartPos.set(	0.0f,
									0.0f,
									m_v3fMinusZExtreme.Z + m_f32CometRedSize );
	m_poEntAsteroidRed->SetIrrPlusPhysicsPosition( m_v3fAsteroidRedStartPos );
	m_poEntAsteroidRed->SetStartPosition( m_v3fAsteroidRedStartPos );

	// calculate blue asteroid starting position
	m_v3fAsteroidBlueStartPos.set(	m_v3fAsteroidBlueStartPos.X - ( m_f32CometRedSize + 30.0f ),
									0.0f,
									m_v3fMinusZExtreme.Z + m_f32CometBlueSize );
	m_poEntAsteroidBlue->SetIrrPlusPhysicsPosition( m_v3fAsteroidBlueStartPos );
	m_poEntAsteroidBlue->SetStartPosition( m_v3fAsteroidBlueStartPos );

	log_msg( 0, "Calculating Geometry: done\n" );
}
